package xyz.cerberu.cet.spider.controller;


import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.apache.shiro.authz.annotation.RequiresUser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import xyz.cerberu.cet.global.domain.Result;
import xyz.cerberu.cet.global.utils.ResultUtils;
import xyz.cerberu.cet.spider.exception.ResourceTypeException;
import xyz.cerberu.cet.spider.service.SpiderManagerService;

import java.lang.reflect.InvocationTargetException;
import java.net.URLEncoder;
import java.time.DateTimeException;
import java.time.LocalDate;

/**
 * @author β世界
 * Created on 21:56
 * @Description 爬虫管理的controller
 */
@Controller
@RequestMapping(value = "/manager")
public class SpiderManagerController {
    private static final Logger logger = LoggerFactory.getLogger(SpiderManagerController.class);

    @Autowired
    private SpiderManagerService managerService;

    private static final int MIN_YEAR = 1990;

    /**
     * @author β世界 on 22:00 2020/8/9
     * 让爬虫去抓取一个动漫的资源更新情况
     * (只允许admin和root用户来进行操作其他非法的操作一律拒绝处理)
     * @param anime: 动漫的名字或者是id标识
     * @param type: 识别动漫的方式
     * @return Result
     **/
    @RequiresUser
    @RequiresRoles(value = {"admin","root"},logical = Logical.OR)
    @ResponseBody
    @RequestMapping(value = "/captureAnimeResource",method = RequestMethod.POST)
    public Result<Object> captureAnimeResource(String anime, String type){
        logger.warn("Manual Spider "+anime);
        // 判断anime是否为空
        if(anime != null && "".equals(anime.trim())){
            return ResultUtils.genErrorResult(5006,"动漫名输入不符合规则");
        }
        // 执行爬虫
        try {
            anime = URLEncoder.encode(anime,"UTF-8");
            managerService.captureResource(anime,type);
        } catch (Exception e) {
            e.printStackTrace();
            if(e instanceof ResourceTypeException){
                return ResultUtils.genErrorResult(5006,e.getMessage());
            }
            return ResultUtils.genErrorResult(5006,"处理失败");
        }
        return ResultUtils.genSuccessResult("成功");
    }

    /**
     * @author β世界 on 13:04 2021/1/17
     * 让爬虫去执行指定的任务
     * @param task: 任务的类型
     * @return com.cet.common.domain.Result
     **/
    @RequiresUser
    @RequiresRoles(value = {"admin","root"},logical = Logical.OR)
    @ResponseBody
    @RequestMapping(value = "/task",method = RequestMethod.POST)
    public Result<Object> executeTask(String task){
        Result<Object> result;
        try {
            managerService.spiderTask(task);
            result = ResultUtils.genSuccessResult("执行成功");
        } catch (InvocationTargetException e) {
            e.printStackTrace();
            result = ResultUtils.genFailResult("任务执行失败,反射方法失败");
        } catch (IllegalAccessException e) {
            e.printStackTrace();
            result = ResultUtils.genFailResult("任务执行失败,无法创建反射方法");
        }
        return result;
    }

    /**
     * 指定日期更新动漫
     * @author β世界 on 13:57 2021/5/31
     * @param year: 日期
     * @param month: 月份
     * @return xyz.cerberu.cet.global.domain.Result<java.lang.Object>
     **/
    @RequiresUser
    @RequiresRoles(value = {"admin","root"},logical = Logical.OR)
    @ResponseBody
    @RequestMapping(value = "/appointTimeAnime",method = RequestMethod.POST)
    public Result<Object> assignTimeUpdateAnime(
            Integer year,
            @RequestParam(required = false,defaultValue = "1") Integer month){

        if(isStandard(year,month)){
            throw new DateTimeException("year = "+year+", month = "+month);
        }

        managerService.appointTimeUpdateAnime(year,month);
        return ResultUtils.genSuccessResult("任务执行成功");
    }

    @RequiresUser
    @RequiresRoles(value = {"admin","root"},logical = Logical.OR)
    @ResponseBody
    @RequestMapping(value = "/appointTimeResource",method = RequestMethod.POST)
    public Result<Object> assignTimeUpdateResource(
            Integer year,
            @RequestParam(required = false,defaultValue = "1") Integer month){
        if(isStandard(year,month)){
            throw new DateTimeException("时间参数错误: year = "+year+", month = "+month);
        }
        managerService.appointTimeUpdateResource(year,month);
        return ResultUtils.genSuccessResult("任务执行成功");
    }

    /**
     * 判断时间是否正常
     * @author β世界 on 22:00 2021/5/31
     * @param year: 年份
     * @param month: 月份
     * @return boolean
     **/
    private boolean isStandard(Integer year,Integer month){
        return year < MIN_YEAR || year > LocalDate.now().getYear() || month < 0 || month > 12;
    }

}
